package com.panda.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.panda.annotation.PageView;
import com.panda.annotation.SystemLog;
import com.panda.entity.po.Article;
import com.panda.entity.po.Category;
import com.panda.entity.po.User;
import com.panda.entity.vo.*;
import com.panda.enums.AppHttpCodeEnum;
import com.panda.mapper.VideoMapper;
import com.panda.service.ArticleService;
import com.panda.service.CategoryService;
import com.panda.service.UserService;
import com.panda.utils.*;
import com.panda.constants.SystemConstants;
import com.panda.mapper.ArticleMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.panda.utils.BeanCopyUtil.copyBeans;
import static com.panda.utils.DataFormatUtil.twoDimensionListSort;

/**
 * (Article)表服务实现类
 *
 * @author makejava
 * @since 2022-03-13 17:21:45
 */
@Service("articleService")
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private UserService userService;

    @Autowired
    private ArticleMapper articleMapper;

    /**
     * 获取所有文章，所有人可以访问
     *
     * @param pageNum
     * @param pageSize
     * @param categoryId
     * @return
     */
    @Override
    @SystemLog(businessName = "获取所有文章")
    public RespondResult<PageVo<ArticleListVo>> getAllArticles(Long id, Integer pageNum, Integer pageSize, Long categoryId, String keyword) {

        LambdaQueryWrapper<Article> articleWrapper = new LambdaQueryWrapper<>();
        //根据用户id查询文章
        articleWrapper.eq(Objects.nonNull(id), Article::getCreateBy, id);

        //判断categoryId字段是否有传值，有就加上判断条件，没有就查询所有
        articleWrapper.eq(Objects.nonNull(categoryId) && categoryId > 0, Article::getCategoryId, categoryId);
        articleWrapper.like(Objects.nonNull(keyword), Article::getTitle,keyword);
        articleWrapper.eq(Article::getDelFlag, SystemConstants.IS_NOT_DELETE);
        //判断文章是否通过审核, 假如是作者自己查看，就不判断
        articleWrapper.eq(!Objects.nonNull(id), Article::getIsAudit, SystemConstants.ARTICLE_STATUS_NORMAL);
        //文章降序
        articleWrapper.orderByDesc(Article::getIsTop);
        //分页
        Page<Article> articlePage = new Page<>(pageNum, pageSize);

        page(articlePage, articleWrapper);
        //对象封装成VO
        List<ArticleListVo> articleListVos = BeanCopyUtil.copyBeans(articlePage.getRecords(), ArticleListVo.class);
        //分页处理，返回给前台
        PageVo<ArticleListVo> pageVo = new PageVo<>(articleListVos, articlePage.getTotal());

        return RespondResult.okResult(pageVo);
    }

    /**
     * 获取文章详情，所有人可以访问
     *
     * @param id
     * @return
     */
    @Override
    @PageView(description = "article")
    @SystemLog(businessName = "获取文章详情")
    public RespondResult<ArticleDetailVo> getArticleDetail(Long id) {
        //通过id获取文章
        Article article = getById(id);
        if (article == null) {
            return RespondResult.errorResult(AppHttpCodeEnum.GET_ARTICLE_ERROR);
        }
        //利用bean拷贝工具，将文章信息装成Vo
        ArticleDetailVo articleDetailVo = BeanCopyUtil.copyBean(article, ArticleDetailVo.class);
        //查询这篇文章的分类
        Long categoryId = articleDetailVo.getCategoryId();
        Category category = categoryService.getById(categoryId);
        User user = userService.getById(article.getCreateBy());
        articleDetailVo.setAvatar(user.getAvatar());
        articleDetailVo.setUsername(user.getUsername());
        if (category != null) {
            //将分类名设置到文章Vo
            articleDetailVo.setCategoryName(category.getCategoryName());
        }
        return RespondResult.okResult(articleDetailVo);
    }

    /**
     * 获取热门文章
     *
     * @return
     */
    @Override
    @SystemLog(businessName = "查看热门文章")
    public RespondResult<List<TopArticleVo>> getTopArticles() {

        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();

        //判断文章是否通过审核
        wrapper.eq(Article::getIsAudit, SystemConstants.ARTICLE_STATUS_NORMAL);
        //降序
        wrapper.orderByDesc(Article::getViews);
        //分页
        Page<Article> page = new Page<>();
        page(page, wrapper);
        List<Article> articles = page.getRecords();

        return RespondResult.okResult(BeanCopyUtil.copyBeans(articles, TopArticleVo.class));

    }

    /**
     * 发布文章，需登陆
     *
     * @param articleVo
     * @return
     */
    @Override
    @SystemLog(businessName = "上传一篇文章")
    public RespondResult<ArticleVo> postArticle(ArticleVo articleVo) {

        try {
            Long userId = SecurityUtils.getUserId();
            //判断用户是否登陆
            if (userId != null) {
                Article article = BeanCopyUtil.copyBean(articleVo, Article.class);
                //设置文章作者
                article.setCreateBy(userId);
                Category category = categoryService.getById(articleVo.getCategoryId());
                article.setCategoryName(category.getCategoryName());
                //保存文章
                save(article);
                return RespondResult.okResult(articleVo);
            }
        } catch (Exception e) {
            return RespondResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);

        }
        return RespondResult.errorResult(AppHttpCodeEnum.ERROR_POST_ARTICLE);

    }

    /**
     * 删除文章，需登陆
     *
     * @param id
     * @return
     */
    @Override
    @SystemLog(businessName = "删除文章")
    public RespondResult deleteArticle(Long id) {
        //判断用户是否登陆
        Long userId;
        try {
            userId = SecurityUtils.getUserId();
        } catch (Exception e) {
            return RespondResult.errorResult(AppHttpCodeEnum.DELETE_ARTICLE_ERROR);
        }
        Article article = getById(id);

        //判断这篇文章的作者，是否是此次登陆用户，不可删除别人的文章
        if (!Objects.equals(article.getCreateBy(), userId)) {
            return RespondResult.errorResult(AppHttpCodeEnum.NO_AUTH);
        }

        UpdateWrapper<Article> updateWrapper = new UpdateWrapper<>();
        //通过id获取需要删除的文章
        updateWrapper.eq("id", id);
        updateWrapper.set("del_flag", "1");

        boolean update = update(updateWrapper);

        //删除
        if (update) {
            //成功
            return RespondResult.okResult();
        }

        return RespondResult.errorResult(AppHttpCodeEnum.DELETE_ARTICLE_ERROR);
    }

    /**
     * 修改文章，需登陆
     *
     * @param id
     * @param articleVo
     * @return
     */
    @Override
    @SystemLog(businessName = "修改文章")
    public RespondResult<ArticleVo> modifyArticle(Long id, ArticleVo articleVo) {

        //判断用户是否登陆
        Long userId;
        try {
            userId = SecurityUtils.getUserId();
        } catch (Exception e) {
            return RespondResult.errorResult(AppHttpCodeEnum.MODIFY_ARTICLE_ERROR);
        }

        //判断是否是文章作者，不可修改他人文章
        if (!Objects.equals(getById(id).getCreateBy(), userId)) {
            return RespondResult.errorResult(AppHttpCodeEnum.NO_AUTH);
        }

        //通过id查询文章
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Article::getId, id);

        //更新
        Article article = BeanCopyUtil.copyBean(articleVo, Article.class);
        //重新审核
        article.setIsAudit("NULL");
        boolean isUpdate = update(article, wrapper);
        if (isUpdate) {
            return RespondResult.okResult(articleVo);
        }
        return RespondResult.errorResult(AppHttpCodeEnum.MODIFY_ARTICLE_ERROR);
    }

    /**
     * 搜索文章
     */
    @Override
    public RespondResult searchArticle(String keyword, Long pageNum) {
        IPage<Article> page = new Page<>();
        //设置每页条数
        page.setSize(12);
        //设置查询第几页
        page.setCurrent(pageNum);

        QueryWrapper<Article> articleQueryWrapper = new QueryWrapper<>();
//        articleQueryWrapper.like("title","测试");
        articleQueryWrapper.like("title",keyword);
//        设置分页
        articleMapper.selectPage(page,articleQueryWrapper);
//        List<Article> articles = articleMapper.selectList(articleQueryWrapper);
        List<Article> articleList = page.getRecords();
        List<ArticleSearchVo> articleSearchVos = BeanCopyUtil.copyBeans(articleList, ArticleSearchVo.class);
        if (Objects.nonNull(articleSearchVos)){
            double pageTotal =(double) page.getPages();
            DividePageVo pageInfo = new DividePageVo( (long) Math.ceil(pageTotal));
//        UserNameListVo userNameListVo = new UserNameListVo(userNameVos, dividePageVo);
//            ArticleSearchListVo articleSearchList = new ArticleSearchListVo(articleSearchVos, pageInfo);
//        System.out.println(articleSearchList);
            PageVo<ArticleSearchVo> articleSearchVoPageVo = new PageVo<>(articleSearchVos, page.getTotal());
            return RespondResult.okResult(articleSearchVoPageVo);
        }
        return RespondResult.errorResult(404,"找不到相关文章");
    }

    /**
     * 文章审核通过
     */
    @Override
    public RespondResult articlePass(Long articleId) {
        UpdateWrapper<Article> articleUpdateWrapper = new UpdateWrapper<>();
        articleUpdateWrapper.eq("id",articleId);
        articleUpdateWrapper.set("is_audit","1");
        boolean isUpdate = update(null, articleUpdateWrapper);
        if (isUpdate){
            return RespondResult.okResult();
        }
        return RespondResult.errorResult(404,"审核失败");
    }

    /**
     * 文章审核不通过
     */
    @Override
    public RespondResult articleNoPass(Long articleId) {
        UpdateWrapper<Article> articleUpdateWrapper = new UpdateWrapper<>();
        articleUpdateWrapper.eq("id",articleId);
        articleUpdateWrapper.set("is_audit",0);
        boolean isUpdate = update(null, articleUpdateWrapper);
        if (isUpdate){
            return RespondResult.okResult();
        }
        return RespondResult.errorResult(404,"审核失败");
    }

    /**
     * 管理后台统计过去一周内文章的投稿量
     */
    @Override
    public RespondResult createdArticleStatistic() {
        List<Map<String, String>> mapList = createArticleCount();
        List<LinkedList<String>> linkedList = twoDimensionListSort(mapList);
        return RespondResult.okResult(linkedList);
    }

    /**
     * 获取待审核文章标题列表
     */
    @Override
    public RespondResult auditArticleTitleList(int pageNum) {
        IPage<Article> page = new Page<>();
        //设置每页条数
        page.setSize(7);
        //设置查询第几页
        page.setCurrent(pageNum);
        QueryWrapper<Article> articleQueryWrapper = new QueryWrapper<>();
        articleQueryWrapper.eq("is_audit", "NULL");
        articleQueryWrapper.select("id", "title");
        page(page, articleQueryWrapper);
        List<Article> records = page.getRecords();
        List<ArticleAuditVo> vos = copyBeans(records, ArticleAuditVo.class);
        double pageTotal = (double) page.getPages();
        DividePageVo dividePageVo = new DividePageVo((long) Math.ceil(pageTotal));
        ArticleAuditListVo articleAuditListVo = new ArticleAuditListVo(vos, dividePageVo);
//        System.out.println(vos);
        if (Objects.nonNull(vos)) {
            return RespondResult.okResult(articleAuditListVo);
        }
        return RespondResult.errorResult(404, "暂无待审核文章");
    }

    /**
     * 获取需要审核文章的内容
     */
    @Override
    public RespondResult auditArticleContent(Long id) {
        QueryWrapper<Article> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        Article article = getOne(queryWrapper);
        if (Objects.nonNull(article)) {
            String content = article.getContent();
            return RespondResult.okResult(content);
        }
        return RespondResult.errorResult(404, "找不到相应文章");
    }

    /**
     * 统计过去一周类目下的文章的投稿量
     */
    @Override
    public RespondResult createdCategoryOfWeekStatistic(String categoryName) {
        List<Map<String, String>> mapList = createdCategoryOfWeek(categoryName);
        List<LinkedList<String>> linkedLists = twoDimensionListSort(mapList);

        return RespondResult.okResult(linkedLists);
    }

//service层封装mapper的自定义方法
    @Override
    public List<Map<String, String>> createArticleCount() {
        return articleMapper.createArticleCount();
    }
    @Override
    public List<Map<String,String>> createdCategoryOfWeek(String categoryName) {
        return articleMapper.createdCategoryOfWeek(categoryName);
    }
}

